package com.cskaoyan.javase._1extends._9override;

/**
 * 方法覆盖的语法
 * 首先方法的覆盖是针对以下成员方法的:
 * [访问权限修饰符] 返回值类型 方法名(形参列表){
 *  //方法体
 * }
 * 注: 成员方法没有static修饰.
 *
 * 在具体讲解方法的覆盖语法之前,我们首先学习一个注解"@Override"
 * 该注解写在子类重写父类方法的上面,用来标记这个方法是重写自父类的方法
 * 如果该注解和方法的语法都没有报错,说明这个方法确实是重写自父类的.
 * 所以我们要求:
 *      只要是该方法重写自父类,一定要加注解
 *      不写注解就重写方法,是错误的做法!!!
 * 之所以写注解:
 *      1.注解标记后不报错,该方法就能够认定是重写自父类的,避免错误的认知.
 *      2.增加代码可读性(重要)
 *
 * 日常开发中,重写父类方法,推荐两种方式:
 *      1.如果明确知道父类中方法的方法名,
 *          可以在子类类体中直接写这个方法名
 *          然后回车即可
 *      2.如果不知道要重写父类哪个方法
 *          需要先查看父类方法再决定
 *          可以使用快捷键"alt + insert"
 *
 * 接下来我们来学习方法的重写的语法:
 * [访问权限修饰符] 返回值类型 方法名(形参列表){
 *   // 方法体
 * }
 * 子类重写父类成员方法:
 *      1.访问权限修饰符是可以修改的
 *          但是只能往更宽松的访问权限去改
 *          子类重写的方法,
 *              不能比父类方法访问权限更严格
 *          当然保持一致也可以.
 *
 *     2.返回值类型实际上是可以改的
 *          但是这个修改不是任意改的.
 *          这个小知识点留给大家中午时测试一下.
 *          从两个角度:
 *              a.基本数据类型返回值类型
 *              b.引用数据类型返回值类型
 *
 *     3.方法名必须严格保持一致,不能改.
 *     4.形参列表必须严格保持一致,不能改.
 *     5.子类重写的方法体没有要求,随便写.
 *
 * 十年之前的面试题:
 * 方法重载(overload) vs 方法重写(override)
 * 不同点:
 *   1.发生的类
 *      方法重载: 必须发生在同一个类中
 *      方法重写: 必须发生在继承中的父子类中,必须要有两个类
 *   2.访问权限修饰符
 *      方法重载: 不关心访问权限修饰符
 *      方法重写: 子类中重写父类的方法,访问权限必须更宽松,或者保持一致.不能更严格.
 *   3.返回值类型
 *      方法重载: 不关心返回值类型
 *      方法重写: 有要求
 *   4.形参列表
 *     方法重载: 要求形参列表必须不一致(方法名相同,形参列表不同,是构造方法重载的唯一条件)
 *     方法重写: 要求形参列表必须一致
 *
 * 共同点:
 *   1.方法名,都要去方法名相同.
 *   2.方法体,都不做要求,随便写.
 *
 *
 *
 *
 * @since 10:59
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo2 {
    public static void main(String[] args) {
        Father fs = new Son();
        fs.test();
        fs.invokeTest();

        Father f = new Father();
        f.test();
        f.invokeTest();
    }
}

class Father {
    public void test() {
        System.out.println("father");
    }

    public void invokeTest() {
        test();
    }
}

class Son extends Father {
    @Override
    public void test() {
        System.out.println("son");
    }

    // @Override
    public void testSon() {
        System.out.println("son only");
    }
}